import json
import re
import logging

from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import render
# Create your views here.
from django.views import View

from apps.goods.models import SKU
from apps.users.models import *
from django_redis import get_redis_connection
from django.contrib.auth import login, authenticate, logout
from django.http.response import JsonResponse, HttpResponse

from utils.views import LoginRequiredJsonMixin

logger = logging.getLogger('django')


class UsernameCountView(View):
    def get(self, request, username):
        """
        校验用户名是否存在
        :param request:  请求对象
        :param username:  用户名
        :return:  Json数据
        """
        # 1、接收前端数据  GET
        # var url = this.host + '/usernames/' + this.username + '/count/'
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
            return JsonResponse({'code': 400, 'errmsg': '用户名不符合要求，请重新输入'})
        # 2、查询数据库数据
        count = User.objects.filter(username__exact=username).count()
        # 3、返回Json数据  {'code':0, 'count':0/1, 'errmsg': 'ok'}
        data = {
            'code': 0,
            'count': count,
            "errmsg": 'ok'
        }
        return JsonResponse(data=data)


class MobileCountView(View):
    def get(self, request, mobile):
        """
        校验手机号是否存在
        :param request: 请求对象
        :param mobile: 手机号
        :return: Json数据
        """
        # 1、接收前端数据  GET
        # var url = this.host + '/mobiles/' + this.mobile + '/count/'
        if not re.match(r'^1[345789]\d{9}$', mobile):
            return JsonResponse({'code': 400, 'errmsg': '手机号不符合要求，请重新输入'})
        # 2、查询数据库数据
        count = User.objects.filter(mobile__exact=mobile).count()
        # 3、返回Json数据
        return JsonResponse({'code': 0, 'count': count, 'errmsg': 'ok'})


class RegisterView(View):
    def post(self, request):
        """
        POST请求  注册账户
        :param request:
        :return:
        """
        # 1、接收前端数据  POST
        # date_bytes = request.body    # bytes类型
        # date_str = date.decode()  # Json类型
        # data_dict = json.loads(date_str)
        date_dict = json.loads(request.body.decode())  # 将JSON字符串，转成python的标准字典
        username = date_dict.get("username")
        password = date_dict.get("password")
        password2 = date_dict.get("password2")
        mobile = date_dict.get("mobile")
        sms_code = date_dict.get("sms_code")
        allow = date_dict.get("allow")
        # 2、校验数据
        # TODO  校验手机号与用户名是否存在
        if not all([username, password, password2, mobile, sms_code, allow]):
            return JsonResponse({'code': 400, 'errmsg': '参数不全'})
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
            return JsonResponse({'code': 400, 'errmsg': '用户名格式不符合要求，请重新输入'})
        if not re.match(r'^[a-zA-Z0-9_-]{8,20}$', password):
            return JsonResponse({'code': 400, 'errmsg': '密码格式不符合要求，请重新输入'})
        if password != password2:
            return JsonResponse({'code': 400, 'errmsg': '两次密码不一致'})
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return JsonResponse({'code': 400, 'errmsg': '手机号格式不符合要求，请重新输入'})
        if allow != True:
            return JsonResponse({'code': 400, 'errmsg': '未勾选”美多商城用户使用协议“'})
        redis_cli = get_redis_connection('verifications_code')
        redis_sms_code = redis_cli.get(mobile)
        if not redis_sms_code:
            return JsonResponse({'code': 400, 'errmsg': '短信验证码已失效'})
        if sms_code != redis_sms_code.decode():
            return JsonResponse({'code': 400, 'errmsg': '短信验证码输入有误'})
        # 3、数据保存到数据库  create_user
        try:
            # User.objects.create(username=username, password=password, mobile=mobile)  # 密码未加密
            user = User.objects.create_user(username=username, password=password, mobile=mobile)
            # print(user, type(user))
            # logger.info(user, type(user))
        except Exception as e:
            return JsonResponse({'code': 0, 'errmsg': '注册失败'})
        # 状态保持
        login(request, user)
        # 4、返回Json数据
        return JsonResponse({'code': 0, 'errmsg': '注册成功'})


class LoginView(View):
    def post(self, request):
        """
        用户登录
        :param request:
        :return:
        """
        # 1、获取前端数据  POST  this.host + '/login/'
        data_dict = json.loads(request.body.decode())
        username = data_dict.get('username')
        password = data_dict.get('password')
        remembered = data_dict.get('remembered')
        # 2、校验数据
        if not all([username, password]):
            return JsonResponse({'code': 400, 'errmsg': '用户名或密码错误'})
        # # 多账号登录（手机号）
        if re.match(r'^1[3-9]\d{9}$', username):
            User.USERNAME_FIELD = 'mobile'
        else:
            User.USERNAME_FIELD = 'username'
        #   Django 封装的校验
        user = authenticate(username=username, password=password)
        if not user:
            return JsonResponse({'code': 400, 'errmsg': '用户名或密码错误'})
        # 3、状态保持，
        login(request, user)
        # 4、是否记住用户
        # 如果value是一个整数，session将在value秒没有活动后过期。
        # 如果value为0，那么用户session的Cookie将在用户的浏览器关闭时过期。
        # 如果value为None，那么session有效期将采用系统默认值， 默认为两周，可以通过在settings.py中设置SESSION_COOKIE_AGE来设置全局默认值。
        if remembered:
            request.session.set_expiry(None)
        else:
            request.session.set_expiry(0)
        # 5、返回Json数据

        # 设置cookie信息
        response = JsonResponse({'code': 0, 'errmsg': '登录成功'})
        from utils.utils import merge_carts_cookie_to_redis
        merge_carts_cookie_to_redis(request, response)
        response.set_cookie('username', user.username, max_age=3600 * 24 * 15)
        return response


class LogoutView(View):
    def delete(self, request):
        """
        退出登录
        :param request:
        :return:
        """
        # 1、接收请求   DELETE  url = this.host + '/logout/'
        # 2、删除session  -- request.session.flush()
        logout(request)
        # 3、删除cookie
        response = JsonResponse({'code': 0, 'errmsg': '退出成功'})
        response.delete_cookie('username')
        # 4、返回响应
        return response


class UserInfoView(LoginRequiredJsonMixin, View):
    """
    判断用户是否登录并返回JSON,用户中心数据展示
    """
    def get(self, request):
        # url = this.host + '/info/'
        info_data = {
            'username': request.user.username,
            'mobile': request.user.mobile,
            'email': request.user.email,
            'email_active': request.user.email_active,
        }
        return JsonResponse({'code': 0, 'errmsg': 'ok', 'info_data': info_data})


class EmailView(View):
    def put(self, request):
        """
        邮件发送
        :param request:
        :return:
        """
        # 1、获取前端数据  PUT url = this.host + '/emails/
        data_dict = json.loads(request.body.decode())
        email = data_dict.get('email')
        # 2、校验数据
        if not email:
            return JsonResponse({'code': 400, 'errmsg': '参数不全'})
        if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
            return JsonResponse({'code': 400, 'errmsg': 'email格式错误'})
        # 3、保存Email
        request.user.email = email
        request.user.save()
        from utils.utils import generate_verify_email_url
        verify_url = generate_verify_email_url(request.user)
        #  ============4、发送邮件=================
        # from django.core.mail import send_mail
        # subject = '测试'
        # message = 'Test'
        # from_email = 'woshizhuyuan2022@163.com'
        # recipient_list = ['964343743@qq.com']
        # html_message = ''
        # send_mail(subject=subject,
        #           message=message,
        #           from_email=from_email,
        #           recipient_list=recipient_list,
        #           html_message=html_message)
        # Mind ------ celery-------------------------
        from apps.users.tasks import send_verify_email
        send_verify_email.delay(email, verify_url)
        # ===========================================
        # 5、返回Json数据
        return JsonResponse({'code': 0, 'errmsg': '添加邮箱成功'})


class VerifyEmailView(View):
    def put(self, request):
        """
        激活邮箱
        :param request:
        :return:
        """
        # 1、前端数据
        token = request.GET.get('token')
        # 2、校验数据
        if not token:
            return JsonResponse({'code': 400, 'errmsg': '参数不全'})
        from utils.utils import check_verify_email
        user = check_verify_email(token)
        if not user:
            return JsonResponse({'code': 400, 'errmsg': '获取user失败'})
        # 3、修改验证状态
        user.email_active = True
        user.save()
        # 4、返回Json数据
        return JsonResponse({'code': 0, 'errmsg': '激活成功'})


class UpdatePasswordView(LoginRequiredJsonMixin, View):
    def put(self, request):
        """
        修改密码
        :param request:
        :return:
        """
        data_dict = json.loads(request.body.decode())
        old_password = data_dict.get('old_password')
        new_password = data_dict.get('new_password')
        new_password2 = data_dict.get('new_password2')
        if not all([old_password, new_password, new_password2]):
            return JsonResponse({'code': 400, 'errmsg': '参数不全'})
        if not request.user.check_password(old_password):
            return JsonResponse({'code': 400, 'errmsg': '原密码输入有误'})
        if not re.match(r'^[a-zA-Z0-9_-]{8,20}$', new_password):
            return JsonResponse({'code': 400, 'errmsg': '新密码格式不符合要求，请重新输入'})
        if new_password != new_password2:
            return JsonResponse({'code': 400, 'errmsg': '新密码输入不一致'})
        try:
            request.user.set_password(new_password)
            request.user.save()
        except Exception as e:
            return JsonResponse({'code': 400, 'errmsg': '密码修改失败'})
        logout(request)
        response = JsonResponse({'code': 0, 'errmsg': 'ok'})
        response.delete_cookie('username')
        return response


class VisitedHistoryView(LoginRequiredJsonMixin, View):
    def get(self, request):
        # 1、接收请求
        # 2、查询数据
        redis_cli = get_redis_connection('visited_history')
        sku_id_list = redis_cli.lrange('user_id:%s' % request.user.id, 0, 4)
        skus = []
        for sku_id in sku_id_list:
            sku = SKU.objects.get(id=sku_id)
            skus.append({
                'id': sku.id,
                'name': sku.name,
                'default_image_url': sku.default_image.url,
                'price': sku.price,
                'comments': sku.comments,
            })
        # 3、返回响应
        return JsonResponse({'code': 0, 'errmsg': 'ok', 'skus': skus})

    def post(self, request):
        # 1、接收前端数据
        data_dict = json.loads(request.body.decode())
        sku_id = data_dict.get('sku_id')
        # 2、校验数据
        try:
            sku_obj = SKU.objects.get(id=sku_id)
        except Exception as e:
            return JsonResponse({'code': 400, 'errmsg': '参数有误'})
        # 3、保存数据（redis）
        redis_cli = get_redis_connection('visited_history')
        # redis_cli.lrem('user_id:%s' % request.user.id, 0, sku_id)
        # redis_cli.lpush('user_id:%s' % request.user.id, sku_id)
        # redis_cli.ltrim('user_id:%s' % request.user.id, 0, 4)
        redis_pipeline = redis_cli.pipeline()
        redis_pipeline.lrem('user_id:%s' % request.user.id, 0, sku_id)
        redis_pipeline.lpush('user_id:%s' % request.user.id, sku_id)
        redis_pipeline.ltrim('user_id:%s' % request.user.id, 0, 4)
        redis_pipeline.execute()
        # 4、返回响应
        return JsonResponse({'code': 0, 'errmsg': 'ok'})

